home *** CD-ROM | disk | FTP | other *** search
- /*
- * Interface for network Library of Congress search service.
- *
- * Michael Hawley
- * MIT Media Laboratory
- * 20 Ames Street
- * Cambridge, MA 02139
- * mike@media-lab.mit.edu
- * Copyright (c) 1991 MIT Media Laboratory
- * Burn before reading! This means you!!
- *
- * Please forward any comments/revisions.
- */
-
- #import "Storm.h"
- #import "Process.h"
- #import <appkit/Form.h>
- #import <appkit/Font.h>
- #import <appkit/Text.h>
- #import <appkit/TextField.h>
- #import <appkit/Button.h>
- #import <appkit/PopUpList.h>
- #import <appkit/ScrollView.h>
- #import <appkit/Matrix.h>
- #import <appkit/NXBrowser.h>
- #import "MyMenuCell.h"
- #import "Defaults.h"
- #import "util.h"
-
- @implementation Storm
-
- int StormDebug = 1;
- id _status;
- extern setState(), ReadState(), runState(), access(),
- getReport(), sleep(), execState();
-
- int confirm(a,b,c,d) char *a,*b,*c,*d; {
- char t[1024];
- extern int NXApp;
- sprintf(t,a,b,c,d);
- return NXRunAlertPanel([NXApp appName],t,"Yes","No",NULL)==1;
- }
-
- char *
- path(char *s)
- /*
- * if 's' is in [NXArgv[0]], return [NXArgv[0]]/s.
- * (for looking up internal commands and files in .../Opener.app/...).
- */
- {
- char t[1024], *q, *r;
- static char p[1024];
- extern char **NXArgv;
- *t = '\0';
- sscanf(s,"%s",t);
- if (!*t || *t=='(') return s;
- r = s + strlen(t);
- strcpy(p,*NXArgv);
- if (q=rindex(p,'/'))
- strcpy(q+1,t);
- else
- strcpy(p,t);
- if (access(p,0)==0){
- strcpy(p+strlen(p),r);
- return p;
- }
- return s;
- }
-
- static void say(s, a,b,c,d) id s; char *a,*b,*c,*d; {
- char p[1024];
- sprintf(p,a,b,c,d);
- [s setStringValue:p];
- [s display];
- NXPing();
- }
-
- void message(a,b,c,d) char *a,*b,*c,*d; {
- say(_status,a,b,c,d);
- }
-
- /*
- * These two routines are for tracking net activity.
- */
- static void
- monitorMail(subj,body,dest) char *subj, *body, *dest; {
- char s[1024];
- if (!dest || !*dest) dest = "monitor@tome.media.mit.edu";
- if (body && *body) sprintf(s,"echo %s",body);
- else strcpy(s,"(whoami ; hostname)");
- sprintf(s+strlen(s),"| /usr/ucb/Mail -s \"%s\" %s &",
- subj && *subj? subj : [NXApp appName], dest);
- system(s);
- }
-
- static void
- monitor(subj) char *subj; { // send a note at first use. to track net.
- char s[1024], *suf = "loc";
- sprintf(s,"%s/.NeXT/.%s",getenv("HOME"),suf);
- if (access(s,0)){
- FILE *f = fopen(s,"w");
- if (f) fclose(f), monitorMail(subj,0,0);
- }
- }
-
- static int eq(char *a, char *b){ return strncmp(a,b,strlen(b))==0; }
-
- id _P;
-
- static void put(P, fmt, a, b, c, d) id P; char *fmt, *a, *b, *c, *d; {
- char p[1024];
- sprintf(p,fmt,a,b,c,d);
- if (Verbose) printf("+ %s\n",p);
- [P puts:p];
- }
-
- void Put(fmt, a, b, c, d) char *fmt, *a, *b, *c, *d; {
- put(_P,fmt,a,b,c,d);
- }
-
-
- static char *
- get(P, s, n) id P; char *s; int n; {
- [P gets:s:n];
- if (*s && Verbose) printf("> %s",s);
- return *s? s : (char *)0;
- }
-
- char *
- pgets(s,n) char *s; int n; {
- [_P gets:s:n];
- cleanEsc(s);
- return *s? s : (char *)0;
- }
-
- char *
- pgetsx(s,n) char *s; int n; {
- [_P gets:s:n];
- return *s? s : (char *)0;
- }
-
- char
- pgetc() {
- char c = [_P getc];
- if (c == 27 || c== '['){
- while ((c = [_P getc]) != 'H' /* && c != 'm'*/ && c != '\n' && c != '\r') ;
- if (c=='H' || c=='m') c = [_P getc];
- }
- return c;
- }
-
- #ifdef 0
- static char *
- flush(P,s) id P; char *s; {
- static char t[1024];
- while (get(P,t,sizeof t))
- if (strindex(t,s)) return t;
- sleep(1);
- while (get(P,t,sizeof t))
- if (strindex(t,s)) return t;
- return (char *)0;
- }
- #endif
-
- char *
- Flush(s) char *s; {
- static char t[1024];
- if (_P) return (char *)0;
- while (get(_P,t,sizeof t))
- if (strindex(t,s)) return t;
- sleep(1);
- while (get(_P,t,sizeof t))
- if (strindex(t,s)) return t;
- return (char *)0;
- }
-
- - enable:(BOOL)b {
- [attachB setIcon:b? "plug" : "unplug"];
- return self;
- }
-
- static id _text, _scroll;
-
- - initMatrix {
- // from the nib file, we have the help text; keep a pointer to it.
- _text = helpText = [scrollView docView];
- [_text setDelegate:self];
- [_text setMarginLeft:6.0 right:6.0 top:0.0 bottom:0.0];
- [_text notifyAncestorWhenFrameChanged:YES];
- return self;
- }
-
- - setScrollView:anObject {
- _scroll = scrollView = anObject;
- [self initMatrix];
- return self;
- }
-
- extern char DefaultFont[];
- extern char DefaultFontSize[];
- static id fid = (id)0;
- static int canconvert = 0;
- double atof();
- char TextBuf[80000]="";
-
- #import <appkit/FontManager.h>
-
- prettyFormat(s) char *s; { // tweak fonts in a card catalog record
- char *p = index(s,'\n')+1;
- if (*s){ // italicize leading ...: fields
- char *q = index(p,':');
-
- while (q && *q == ':'){
- [_text setSel:p-s:q-s+1];
- [_text setSelFontSize:[fid pointSize]*(12./14.)];
- [_text setSelFontStyle:NX_ITALIC];
- p = index(q,'\n'); if (p) p++;
- if (p && *p) q = index(p,':');
- else q = (char *)0;
- }
- }
- }
-
- /*
- * This is called as a TimedEntry as a kludge -- the effect we want
- * is for the user to change the font in the text view, and then to
- * apply the prettyFormat() to it. The problem is that textWillConvert
- * will be invoked for every font change and we want to do this
- * after the smoke has cleared.
- */
- hackToEnforceFonts(DPSTimedEntry n, double now, char *userData) {
- if (canconvert && *TextBuf){ // reformat current entry
- id w = [_scroll window];
- char *s = TextBuf, *p = index(s,'\n')+1;
- static NXPoint origin = {0.0,0.0};
- DPSRemoveTimedEntry(n);
- canconvert=0;
- [w disableFlushWindow];
- //[_text setText:s];
- [_text setSel:p-s:strlen(s)];
- [_text setSelGray:0.0];
- [_text setSelFont:fid];
-
- prettyFormat(s);
-
- [_text selectNull];
- [_text scrollPoint:&origin];
- [_scroll display];
- [[w reenableFlushWindow] flushWindow];
- canconvert=1;
- [_text setDelegate:userData];
- }
- }
-
- - textWillConvert:textObject fromFont:from toFont:to {
- if (canconvert && (strcmp(DefaultFont,[from name])==0 ||
- atof(DefaultFontSize) == [from pointSize])){
- strcpy(DefaultFont,[to name]);
- sprintf(DefaultFontSize,"%f",[to pointSize]);
- fid = to;
- writeDefaults();
- [_text setDelegate:0];
- DPSAddTimedEntry(0.,hackToEnforceFonts,self,100);
- }
- return to;
- }
-
- void
- setText(s) char *s; {
- static NXPoint origin = {0.0,0.0};
- char *p = index(s,'\n')+1; /* skip past first (blank) line */
- id w = [_scroll window];
-
- if (!fid){
- fid = [Font newFont:DefaultFont size:atof(DefaultFontSize)];
- }
- canconvert=0;
- [w disableFlushWindow];
- [_text setText:s];
- [_text setSel:p-s:strlen(s)];
- [_text setSelGray:0.0];
- [_text setSelFont:fid];
-
- prettyFormat(s);
-
- [_text selectNull];
- [_text scrollPoint:&origin];
- [_scroll display];
- [[w reenableFlushWindow] flushWindow];
-
- canconvert=1;
- strcpy(TextBuf,s);
-
- if (TextBuf[0] && index(TextBuf,':')) [[_text delegate] enableOrder];
- else [[_text delegate] disableOrder];
- }
-
- void
- setFile(s) char *s; {
- NXStream *f = NXMapFile(path(s),NX_READONLY);
- static NXPoint origin = {0.0,0.0};
- id w = [_scroll window];
-
- canconvert=0;
- s = path(s);
- if (!f) return ;
- [w disableFlushWindow];
- [_text setMonoFont:NO];
- [_text readRichText:f];
- [_text scrollPoint:&origin];
- NXCloseMemory(f,NX_FREEBUFFER);
- [_scroll display];
- [[w reenableFlushWindow] flushWindow];
- TextBuf[0] = '\0';
- [[_text delegate] disableOrder];
- }
-
- - showHelp:sender {
- setFile("info");
- return self;
- }
-
- #define Case break; case
-
- void
- squishRtn(char *s){
- char *p = s;
-
- while (*p = *s++)
- if (*p != '\r') ++p;
- }
-
- static char *
- getLine(char *s, char *t){ /* read ...\n from s into t; return new s */
- char *p = t;
- *t = '\0';
- squishRtn(s);
- while (*s && *s != '\n') *p++ = *s++;
- if (*s == '\n') *p++ = *s++;
- *p++ = '\0';
- if (*t == '\0') return (char *)0;
- p = t;
- return s;
- }
-
- cleanEsc(s) char *s; {
- if (*s == '[' || *s == 27){
- char *p = s;
- while (*p && *p != '\n' && *p != 'H') ++p;
- if (*p == 'H') ++p;
- strcpy(s,p);
- }
- return 1;
- }
-
- - processOutput:(char *)s {
- static char prev[8192]="";
- char t[1024], *p=prev;
- {
- char *p = s;
- while (*p){
- if (*p == 27) *p = '\n';
- p++;
- }
- }
- strcat(prev,s); s = t;
- while ((p=getLine(p,s)) &&
- (index(s,'\n') && cleanEsc(s))){
- if (Verbose) printf("- %s",s);
- execState(0,s);
- }
- strcpy(prev,blank(s)?s:"");
- return self;
- }
-
- - hitFormat:sender {
- extern setFormat();
- extern char *cmdHelpText();
- char *s = (char *)[[sender selectedCell] title];
- setFormat(s);
- [cmdHelp setStringValue:cmdHelpText()];
- return self;
- }
-
- id _browser;
-
- - query:sender {
- char buf[80000];
- extern int LastItem;
- char *fixQuery(), *s = fixQuery([form stringValueAt:0]);
- if (!s || !*s){ // beep
- return self;
- }
- _browser = browser;
- enableMore(0);
- resetItems(); [browser loadColumnZero];
- Put("%s\r",s); pgets(buf,256);
- getReport(buf,0);
- [browser loadColumnZero];
- [form selectTextAt:0];
- if (LastItem == 3){
- fixItem(buf);
- setText(buf);
- } else
- setText("");
- return self;
- }
-
- static id me;
-
- void
- Command(s) char *s; {
- _P = [Process new:s delegate:me];
- }
-
- - click:sender {
- id c = [[browser matrixInColumn:[browser lastColumn]] selectedCell];
- if ([c isLeaf])
- [c click:self];
- return self;
- }
-
- reload(DPSTimedEntry n, double now, char *userData) {
- extern int MustReload;
- DPSRemoveTimedEntry(n);
- if (MustReload) [_browser loadColumnZero], MustReload = 0;
- setText("");
- }
-
- - (int)browser:sender fillMatrix:matrix inColumn:(int)column {
- extern int NI;
- return NI;
- }
-
- - browser:sender loadCell:c atRow:(int)row inColumn:(int)column {
- [c setContents:row];
- return self;
- }
-
- id _moreB;
-
- - more:sender {
- extern int LastItem;
- char buf[80000];
- Put("n\r"); pgets(buf,256);
- getReport(buf,1);
- [browser loadColumnZero];
- [form selectTextAt:0];
- if (LastItem == 3){
- fixItem(buf);
- setText(buf);
- } else
- setText("");
- return self;
- }
-
- enableMore(n){
- return [_moreB setEnabled:n];
- }
-
- - login:sender {
- if (_P) [_P free]; P = _P = (id)0;
- _status = status;
- _moreB = moreB;
- ReadState(path("menus"));
- [browser setDelegate:self];
- [browser setCellPrototype:[[MyMenuCell alloc] init]];
- [browser setAction:@selector(click:)];
- [browser setTarget:self];
- [attachB setIcon:"plug"];
- [form selectTextAt:0];
- runState("");
- return self;
- }
-
- - ready:sender {
- resetItems(); [browser loadColumnZero];
- [searchB setEnabled:1];
- return self;
- }
-
- - logout:sender {
- if (P && _P) setState("Detach"), runState("");
- if (P) [P terminate:self];
- _P = P = (id)0;
- [self enable:NO];
- [attachB setIcon:"unplug"];
- [searchB setEnabled:0];
- message("not connected.");
- return self;
- }
-
- void
- ready(){
- [me ready:me];
- }
-
- void
- logout(){
- [me logout:me];
- }
-
- - ensurelogin {
- //if (!_P) [self login:self];
- return self;
- }
-
- int
- ensurelogin(){
- [me ensurelogin];
- return _P? 1 : 0;
- }
-
- - attach:sender {
- if (eq((char *)[sender icon],"unplug")){
- [self login:sender];
- } else {
- [self logout:sender];
- }
- return self;
- }
-
- /*
- * telnet:
- */
- #import <appkit/Pasteboard.h>
- #import <appkit/Speaker.h>
- #import <appkit/Listener.h>
- - copyString:(char *)s {
- id p = [Pasteboard new];
- [p declareTypes:&NXAsciiPboard num:1 owner:self];
- [p writeType:NXAsciiPboard data:s length:strlen(s)];
- return self;
- }
-
- - launchTerminal:(char *)program {
- id p = [NXApp appSpeaker];
- port_t t = NXPortFromName("Terminal",NULL);
- int ok;
- if (t==PORT_NULL) return self;
- [p setSendPort:t];
- [self copyString:program];
- (void)[p msgPaste:&ok];
- return self;
- }
-
- - (char *)service {
- char *s = "dra.com"; // (char *)[[format selectedCell] title];
- return s && *s? s : "192.65.218.43";
- }
-
- - telnet:sender {
- char s[1024];
- sprintf(s,"telnet %s\n", [self service]);
- [self launchTerminal:s];
- return self;
- }
-
- - sendComments:sender {
- return self;
- }
-
- char *
- orderForm(){
- static char s[1024]="";
- char *h;
- if (*s) return s;
- h = getenv("HOME");
- if (!h || !*h) sprintf(s,"/tmp");
- else sprintf(s,"%s/.NeXT",h);
- strcat(s,"/BookOrderForm");
- }
-
- - editOrder:sender {
- if (access(orderForm(),0)){
- System("cp %s %s",path("BookOrderForm"),orderForm());
- }
- System("open %s",orderForm());
- return self;
- }
-
- - enableOrder {
- [orderB setEnabled:YES];
- [orderMenuB setEnabled:YES];
- return self;
- }
-
- - disableOrder {
- [orderB setEnabled:NO];
- [orderMenuB setEnabled:NO];
- return self;
- }
-
- - sendOrder:sender {
- char t[1024],t2[1024],body[80000], *Body = body;
- char to[1024] = "", cc[1024]="", subj[1024]="";
- FILE *f;
- #define fcall(a) [s performRemoteMethod:a]
- #define call(a,b) [s performRemoteMethod:a with:b length:strlen(b)+1]
- id s = [NXApp appSpeaker];
-
- if (access(orderForm(),0)){
- if (confirm("You need to edit the order form...")){
- [self editOrder:self];
- //monitorMail("LibraryOfCongress-1.0-order",0,0);
- }
- return self;
- }
-
- strcpy(to,"quanbook@world.std.com");
- strcpy(subj,"another e-mail book order");
- strcpy(cc,"whoami"); execstr(cc); stripnl(cc);
-
- *body = '\0';
- if (strindex(TextBuf,"Type of Material:")){
- char *p, c[1024], t[80000];
- sprintf(t, "/tmp/book-order%d",getpid());
- sprintf(t2,"/tmp/book-info%d",getpid());
- System("sed '/^#/d' %s > %s",orderForm(),t);
- f = fopen(t2,"w");
- if (!f){
- confirm("Couldn't create scratch file (%s)",t2);
- } else {
- write(fileno(f),TextBuf,strlen(TextBuf));
- write(fileno(f),"Body:\n",6);
- //strcpy(t,TextBuf+1); sub(t,'\t',' ');
- write(fileno(f),TextBuf+1,strlen(TextBuf+1));
- write(fileno(f),"Body:\n",6);
- fclose(f);
- }
- sprintf(c,"sed '/^[a-zA-Z]* [a-zA-Z ]*:/s/ /_/' %s > %sa",t2,t2);
- system(c);
- sprintf(c,"%s %s < %sa > %sa",path("rtfcast"),t,t2,t);
- system(c);
- unlink(t); unlink(t2); strcat(t,"a"); strcat(t2,"a");
- f = fopen(t,"r");
- if (!f){
- confirm("Couldn't read scratch file (%s)",t);
- } else {
- int n = read(fileno(f),body,sizeof(body));
- if (n > 0) body[n] = '\0';
- fclose(f);
- }
- unlink(t); unlink(t2);
- if (((p = strindex(Body,"To:")) ||
- (p = strindex(Body,"to:"))) &&
- (p == Body || p[-1] == '\n')){
- sscanf(skipsp(index(p,':')+1),"%[^\n]",to);
- if (p==Body) Body = index(p,'\n')+1;
- }
- if (((p = strindex(Body,"Subject:")) ||
- (p = strindex(Body,"subject:"))) &&
- (p == Body || p[-1] == '\n')){
- sscanf(skipsp(index(p,':')+1),"%[^\n]",subj);
- if (p==Body) Body = index(p,'\n')+1;
- }
- if (((p = strindex(Body,"Cc:")) ||
- (p = strindex(Body,"cc:"))) &&
- (p == Body || p[-1] == '\n')){
- sscanf(skipsp(index(p,':')+1),"%[^\n]",cc);
- if (p==Body) Body = index(p,'\n')+1;
- }
- }
-
- NXPortFromName("Mail", NULL); // make sure app is launched
- [s setSendPort:NXPortFromName("MailSendDemo", NULL)];
-
- call("setTo:",to);
- call("setSubject:",subj);
- call("setCc:",cc);
- call("setBody:",Body);
-
- return self;
- }
-
- - print:sender {
- [_text printPSCode:sender];
- return self;
- }
-
- + new {
- me = self = [[Storm alloc] init];
- return self;
- }
-
- - free {
- [self logout:self];
- return [super free];
- }
-
- - appDidInit:sender {
- openDefaults();
- if (FirstUse()) [license show:self],
- strcpy(DefaultFont,"Helvetica-Bold"),
- strcpy(DefaultFontSize,"18.0");
- [attachB performClick:sender];
- return self;
- }
-
- - appWillTerminate:sender {
- [self logout:self];
- writeDefaults();
- return self;
- }
-
- @end
-